package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"sync"
	"time"
)

func main() {

	// 每个协程请求次数：
	count := 10
	// 定义并发数：
	size := 10
	// 定义请求url
	url := "https://www.baidu.com"
	// 创建一个缓冲管道存放结果
	ch := make(chan Result, count*size)
	// 创建一个请求
	req := &Request{
		Url: url,
	}
	var wg sync.WaitGroup
	// 创建协程
	for i := 0; i < size; i++ {
		wg.Add(1)
		go func() {
			for i := 0; i < count; i++ {
				Task(req, ch)
			}
			wg.Done()
		}()
	}
	wg.Wait()

	// 取出结果
	var re []int64
	for i := 0; i < count*size; i++ {
		r := <-ch
		re = append(re, r.ResponseTime.Milliseconds())
	}

	// 排序
	average := SortSlice(re)

	fmt.Println("共计请求", len(re), "次")

	fmt.Println("第95%的响应时间", re[95]/1000, "s")

	fmt.Println("平均响应时间", average, "s")
}

// 任务
func Task(request *Request, ch chan Result) {
	start := time.Now()
	url := request.Url
	success := Get(url)
	// 获取时间并返回
	ch <- Result{
		Start:        TimeToUnix(start),
		ResponseTime: TimeSince(start),
		Success:      success == true,
	}
}

/*对切片排序 并且返回平均时间*/
func SortSlice(slice []int64) int64 {
	average := int64(0)
	for i := 0; i < len(slice)-1; i++ {
		average += slice[i]
		//遍历i位以后的所有元素，如果比i位元素小，就和i位元素互换位置
		for j := i + 1; j < len(slice); j++ {
			if slice[j] < slice[i] {
				slice[i], slice[j] = slice[j], slice[i]
			}
		}
	}
	return average / (int64(len(slice))) / 1000
}

// Get 请求url,成功调用了就直接返回true
func Get(url string) bool {
	req, _ := http.NewRequest("GET", url, nil)
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		fmt.Println("GET请求失败了", err)
	} else {
		defer res.Body.Close()
		_, err := ioutil.ReadAll(res.Body)
		if err == nil {
			return true
		}
		//fmt.Println("res:", string(body))
	}
	return false
}

type Result struct {
	Start int64

	ResponseTime time.Duration

	Success bool
}

type Request struct {
	Url string
}

// time 转时间戳
func TimeToUnix(op time.Time) int64 {
	return op.Unix() //time.Now()是当前时间（Time类型）
}

// 时间差
func TimeSince(op time.Time) time.Duration {
	return time.Since(op)
}
